<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <title>05-axios取消请求</title>
  <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.min.js"></script>
</head>
<!-- 取消请求两种方式：
  一、CancelToken
    2. axios.CancelToken: 用于创建取消请求的 token 对象 
    3. axios.isCancel(): 是否是一个取消请求的错误 

  从0.22.0版本，CancelToken被废弃，还可以用但是不推荐，推荐使用AbortController
  二、AbortController
    const controller = new AbortController();

      axios.get('/foo/bar', {
        signal: controller.signal
      }).then(function(response) {
        //...
      });
      // cancel the request
      controller.abort()
    这种方式有个问题，取消一次之后，就无法发送请求
 -->

<body>
  <button id="addPersonBtn">点击添加一个人</button>
  <input type="text" id="personName" placeholder="请输入姓名">
  <input type="text" id="personAge" placeholder="请输入年龄">
  <br><br>
  <button id="testBtn">点击获取测试信息</button>
  <br><br>
  <button id="cancelTestBtn">点击取消获取测试信息</button>

  <script>
    //获取dom节点
    const addPersonBtn = document.getElementById('addPersonBtn');
    const testBtn = document.getElementById('testBtn');
    const cancelTestBtn = document.getElementById('cancelTestBtn');
    const personName = document.getElementById('personName');
    const personAge = document.getElementById('personAge');


    // 添加axios全局默认配置
    //axios_0.27.2版本可以将全局默认配置写成对象形式，但是替换掉了axios原本的config，就不能和拦截器一起使用
    /* axios.defaults = {
      baseURL: 'http://localhost:5000',             //配置全局默认请求基础地址
      timeout: 2000,                                //配置全局默认超时时间
      headers: { token: 'er908s0rfsjflxmvnljf' },   //配置全局默认请求头
    }; */
    axios.defaults.baseURL = 'http://localhost:5000';             //配置全局默认请求基础地址

    // 一、CancelToken
    // 创建取消请求的 token 对象 
    const { CancelToken, isCancel } = axios;
    // console.log(CancelToken);
    //定义一个变量保存取消请求方法
    let cancel;

    /* //创建取消请求控制器
    const controller = new AbortController();
    console.log(controller);
    console.log(controller.signal); */


    // 添加请求拦截器
    axios.interceptors.request.use((config) => {
      //对请求进行检查或配置进行特定处理
      //在请求拦截器中配置取消请求
      // if (cancel) cancel();
      // config.cancelToken = new CancelToken(function executor (c) {
      //   cancel = c;
      // });
      // if (config.url.match(/test/)) config.timeout = 2000;
      if (config.url.match(/person/)) config.headers.token = '131safafaf';
      return config;   //必须将请求配置返回，否则就不会发出任何请求
    });

    //添加响应拦截器
    axios.interceptors.response.use(
      (response) => {
        // console.log(typeof response.data);
        // if (!(response.data instanceof Object)) return '返回的数据不是json对象'
        return response.data;  //必须将响应返回，否则axios接受不到response
      },
      (error) => {
        if (isCancel(error))
        {
          console.log('取消请求');
        } else
        {
          console.log('请求出错了', error);
        }
        return new Promise(() => { });   //终止Promise链，这样后面axios请求使用await就可以不用try...catch处理
      });

    // 添加一个人，年龄和名字--发送POST请求--携带json编码参数或urlencoded编码
    addPersonBtn.onclick = async () => {
      // 完整版
      const response = await axios({
        url: '/person11',                                               //请求地址
        method: 'POST',                                               //请求方式
        data: { name: personName.value, age: personAge.value },       //携带请求体参数，json编码 
      });
      console.log(response);
    };

    // 获取测试信息
    testBtn.onclick = async () => {
      // if (cancel) cancel();   //防止发送重复请求
      const response = await axios({
        url: '/test1?delay=2000',
        method: 'GET',
        //配置取消请求对象，对象名称必须是cancelToken
        // cancelToken: new CancelToken(function executor (c) {
        //   cancel = c;
        // })
        // signal: controller.signal
      });
      console.log(response);
    };

    //取消获取测试信息
    cancelTestBtn.onclick = () => {
      // controller.abort();
      cancel('取消请求');
    };


  </script>
</body>

</html>